import React, { useCallback, useContext, useMemo, useRef } from 'react';

import { Input as AInput } from 'antd';
import { useFocused, useSelected } from 'slate-react';

import { FontFamilyConfig, FontSizeConfig } from '../../constants';
import { useEmitSlateItemClick, useShareDocEditorData } from '../../hooks';
import { SlateElementProps } from '../../types';
import { createClassNameMark } from '../../utils';
import { InlineChromiumBugfix } from '../inline-chromium-bugfix';

import SlateEditorContext from './../../SlateEditorContext';


import Style from './main.module.scss';

const classNames = createClassNameMark(Style);

const MAX_LENGTH = 20;

export const Input = React.memo(function Input({ attributes, children, element }: SlateElementProps) {

  const {
    onSlateInputDataChanged
  } = useContext(SlateEditorContext);

  const prop = `${element.id}/${element.mark}`;
  const [data, setData] = useShareDocEditorData([prop]);
  const textData = (element.children?.[0] || {}) as unknown as { [format: string]: boolean };
  const value = `${data[prop] ?? (element.initialVal || '')}`;
  const inputWidth = useMemo(() => {
    const text = `${value || ''}`;
    const length = text.length;
    // eslint-disable-next-line no-control-regex
    const halfLength = text.match(/[\u0000-\u00ff]/g)?.length || 0;
    return `${halfLength * 0.5 + length - halfLength + 0.5}em`;
  }, [value]);
  const selected = useSelected();
  const focused = useFocused();
  const dataHasBeenEdited = useRef(false);
  const onChange: React.ChangeEventHandler<HTMLInputElement> = useCallback(
    (e) => {
      dataHasBeenEdited.current= true;
      setData({
        [prop]: e.target.value,
      });
    },
    [prop, setData],
  );


  const onClick = useEmitSlateItemClick(element);

  const handleKeyUp = (e) => {
    e.stopPropagation();
  }

  const handleMouseUp = (e) => {
    e.stopPropagation();
  }

  const handleMouseDown = (e) => {
    e.stopPropagation();
  }

  const handleBeforeInput = (e) => {
    e.stopPropagation();
  };

  const handleCompositionEnd = (e) => {
    e.stopPropagation();
  };

  const handleInput = (e) => {
    e.stopPropagation();
  }

  const handleKeyDown = (e) => {
    const {
      code,
      key
    } = e;
    if (code === 'Enter') {
      e.preventDefault();
      e.stopPropagation();
    }
    e.stopPropagation();
  };

  const handleBlur = (e: any) => {
    if (dataHasBeenEdited.current) {
      onSlateInputDataChanged(data);
    }
    e.preventDefault();
    e.stopPropagation();
  };
  
  return (
    <span {...attributes} contentEditable={false}>
      <AInput
        maxLength={MAX_LENGTH}
        className={classNames({
          'doc-input': true,
          'doc-input--del': textData.delete,
          'doc-input--light': selected && focused,
          'doc-input--sup': textData.sup,
          'doc-input--sub': textData.sub,
          'doc-input--underline': textData.underline,
          'doc-input--italic': textData.italic,
          'doc-input--bold': textData.bold,
        })}
        value={value}
        style={{
          width: inputWidth,
          maxWidth: `${MAX_LENGTH}em`,
          color: textData.color as unknown as string,
          backgroundColor: textData.bgColor as unknown as string,
          fontSize: (textData.fontSize as unknown as string) || FontSizeConfig.cp,
          fontFamily: (textData.fontFamily as unknown as string) || FontFamilyConfig.cp,
        }}
        onChange={onChange}
        onClick={onClick}
        onBlur={handleBlur}
        // onMouseDown={handleMouseDown}
        onKeyDown={handleKeyDown}
        onBeforeInput={handleBeforeInput}
        onCompositionEnd={handleCompositionEnd}
        onInput={handleInput}
        onKeyUp={handleKeyUp}
        onMouseUp={handleMouseUp}
      />
      <InlineChromiumBugfix />
      {children}
      <InlineChromiumBugfix />
    </span>
  )
});
